package com.ruoyi.ruoyixingyue.modules.utils.oss;

import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.*;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.ruoyi.ruoyixingyue.modules.utils.videoUtil.VideoUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.FileEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;
import java.util.UUID;

//OSS上传工具类  QYF
@Slf4j
public class UploadFileToOssUtils {


    public final static Integer EXPIRE_TIME = 900;
    public final static SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
    //临时上传RAM
    public final static String TEMP_UPLOAD_ACCESS_KEY_ID = "LTAI5tQ9xucwL8NQrptxCYnC";
    public final static String TEMP_UPLOAD_ARN = "acs:ram::1484273403735569:role/ramosstest";
    public final static String TEMP_UPLOAD_ACCESS_KEY_SECRET = "eYGs9N77WqdZ2k1zo3avdGOXCvVbG7";
    //密匙keyId
    // private final static String ACCESS_KEY_ID = "LTAI5t9kxRL774pqZRgfX7Cm";
    private final static String ACCESS_KEY_ID = "LTAI5tQTxYJ8et2CM4kqkF62";
    //密匙keySecret
    // private final static String ACCESS_KEY_SECRET = "UeDbJo8I5yyaFUQerhUksWHT7Wq4An";
    private final static String ACCESS_KEY_SECRET = "DtAcK4eSyxmPRo6IFmfsPJsLTBynBT";
    private final static String BASE_URL = "https://meinvjianhao.oss-cn-hangzhou.aliyuncs.com/";
    //oss所在域
    private final static String END_POINT = "oss-cn-hangzhou.aliyuncs.com";
    //bucketName 名称
    // private final static String BUCKET_NAME = "hh-caa-chuanmei";
    private final static String BUCKET_NAME = "meinvjianhao";
    public static Long EXPIRE_DATE_TIME = 0L;
    public static JSONObject CredentialsJSON = null;


    public static void tmpUpload(String tmpUrl, File file) throws IOException {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;

        try {
            HttpPut put = new HttpPut(tmpUrl);
            put.setEntity(new FileEntity(file));
            put.addHeader("Content-Type", "application/octet-stream");
            httpClient = HttpClients.createDefault();

            response = httpClient.execute(put);
        } finally {
            file.delete();
        }
    }

    public static String getTmpUrl(String objectName, String contentType) {
        JSONObject stsCredentials = getSTSCredentials();
        String accessKeyId = stsCredentials.getString("accessKeyId");
        String accessKeySecret = stsCredentials.getString("accessKeySecret");
        String securityToken = stsCredentials.getString("securityToken");
        // 从STS服务获取临时访问凭证后，您可以通过临时访问密钥和安全令牌生成OSSClient。
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build("https://" + END_POINT, accessKeyId, accessKeySecret, securityToken);

        try {
            // 创建请求。
            GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(BUCKET_NAME, BUCKET_NAME + "/" + objectName);
            // 设置HttpMethod为PUT。
            generatePresignedUrlRequest.setMethod(HttpMethod.PUT);
            // 设置ContentType。
            generatePresignedUrlRequest.setContentType(contentType);
            // 设置签名URL过期时间，单位为毫秒。
            Date expiration = new Date(new Date().getTime() + EXPIRE_TIME * 1000);
            generatePresignedUrlRequest.setExpiration(expiration);
            // 生成签名URL。
            URL url = ossClient.generatePresignedUrl(generatePresignedUrlRequest);
            return url.toString();
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        throw new RuntimeException("获取临时url失败,请稍后重试");
    }

    /**
     * 获取OSS Web直传所需临时签证
     *
     * @return
     */
    public static JSONObject getSTSCredentials() {
        long current = new Date().getTime();
        if (EXPIRE_DATE_TIME > current) {
            if (Objects.nonNull(CredentialsJSON)) {
                return CredentialsJSON;
            }
        }
        // STS接入地址，例如sts.cn-hangzhou.aliyuncs.com。
        String endpoint = "sts.cn-hangzhou.aliyuncs.com";
        // 填写步骤1生成的访问密钥AccessKey ID和AccessKey Secret。
        String AccessKeyId = TEMP_UPLOAD_ACCESS_KEY_ID;
        String accessKeySecret = TEMP_UPLOAD_ACCESS_KEY_SECRET;
        // 填写步骤3获取的角色ARN。
        String roleArn = TEMP_UPLOAD_ARN;
        // 自定义角色会话名称，用来区分不同的令牌，例如可填写为SessionTest。
        String roleSessionName = UUID.randomUUID().toString();

        // 以下Policy用于限制仅允许使用临时访问凭证向目标存储空间examplebucket上传文件。
        // 临时访问凭证最后获得的权限是步骤4设置的角色权限和该Policy设置权限的交集，即仅允许将文件上传至目标存储空间examplebucket下的exampledir目录。
        try {
            // regionId表示RAM的地域ID。以华东1（杭州）地域为例，regionID填写为cn-hangzhou。也可以保留默认值，默认值为空字符串（""）。
            String regionId = "";
            // 添加endpoint。适用于Java SDK 3.12.0及以上版本。
            DefaultProfile.addEndpoint(regionId, "Sts", endpoint);
            // 添加endpoint。适用于Java SDK 3.12.0以下版本。
            // DefaultProfile.addEndpoint("",regionId, "Sts", endpoint);
            // 构造default profile。
            IClientProfile profile = DefaultProfile.getProfile(regionId, AccessKeyId, accessKeySecret);
            // 构造client。
            DefaultAcsClient client = new DefaultAcsClient(profile);
            final AssumeRoleRequest request = new AssumeRoleRequest();
            // 适用于Java SDK 3.12.0及以上版本。
            request.setSysMethod(MethodType.POST);
            // 适用于Java SDK 3.12.0以下版本。
            //request.setMethod(MethodType.POST);
            request.setRoleArn(roleArn);
            request.setRoleSessionName(roleSessionName);
            request.setPolicy(null); // 如果policy为空，则用户将获得该角色下所有权限。
            request.setDurationSeconds((long) (EXPIRE_TIME)); // 设置临时访问凭证的有效时间为3600秒。
            final AssumeRoleResponse response = client.getAcsResponse(request);
            JSONObject resInfo = new JSONObject();
            resInfo.put("expiration", response.getCredentials().getExpiration());
            resInfo.put("accessKeyId", response.getCredentials().getAccessKeyId());
            resInfo.put("accessKeySecret", response.getCredentials().getAccessKeySecret());
            resInfo.put("securityToken", response.getCredentials().getSecurityToken());

            Date parse = SIMPLE_DATE_FORMAT.parse(response.getCredentials().getExpiration());
            CredentialsJSON = resInfo;
            EXPIRE_DATE_TIME = parse.getTime() + 8 * 60 * 60 * 1000;
            return resInfo;
        } catch (ClientException e) {
            log.error("Failed：");
            log.error("Error code: " + e.getErrCode());
            log.error("Error message: " + e.getErrMsg());
            log.error("RequestId: " + e.getRequestId());
        } catch (ParseException e) {
            log.error("日期转换异常", e);
            throw new RuntimeException(e);
        }
        return new JSONObject();
    }

    public static void deleteFile(String url) {
        try {
            String objectName = url.replace(BASE_URL + BUCKET_NAME + "/", "");
            // 创建OSSClient实例。
            OSS ossClient = new OSSClientBuilder().build(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);

            // 删除文件或目录。如果要删除目录，目录必须为空。
            ossClient.deleteObject(BUCKET_NAME, objectName);
        } catch (Exception ex) {
            log.error("删除文件发生异常 {}", ex);
            throw new RuntimeException("删除OSS文件发生异常");
        }
    }

    /**
     * 上传单个文件到OSS
     *
     * @param multipartFile 上传文件
     * @return url 附件地址
     * @Author QYF
     * @Date 2021/08/10 PM 5:37
     */
    public static String uploadFile(MultipartFile multipartFile) throws OSSException {
        // 创建 oss 对象
        OSSClient client = null;
        // 获取文件后缀
        String suffix = Objects.requireNonNull(multipartFile.getOriginalFilename()).substring(multipartFile.getOriginalFilename().lastIndexOf("."));

        // 拼接oss路劲 /hh-fms/2021/08/10/当前时间戳.后缀
        StringBuilder filePathSub = new StringBuilder();
        filePathSub.append(BUCKET_NAME);
        Calendar calendar = Calendar.getInstance();
        String filePath = filePathSub.append("/")
                .append(calendar.get(Calendar.YEAR)).append("/")
                .append(calendar.get(Calendar.MONTH) + 1).append("/")
                .append(calendar.get(Calendar.DAY_OF_MONTH)).append("/")
                .append(new Date().getTime()).append(suffix).toString();
        try (InputStream inputStream = multipartFile.getInputStream()) {
            // 存入oss
            client = new OSSClient(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
            ObjectMetadata objectMeta = new ObjectMetadata();
            objectMeta.setContentType(multipartFile.getContentType());
            objectMeta.setContentDisposition(multipartFile.getName());
            client.putObject(BUCKET_NAME, filePath, inputStream, objectMeta);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (client != null) {
                client.shutdown();
            }
        }
        return BASE_URL + filePath;
    }

    /**
     * 上传视频返回：路径 视频大小 视频长度
     * @Author 卢壮志
     * @param multipartFile
     * @return
     * @throws OSSException
     */
    public static UploadVideoDto uploadVideo(MultipartFile multipartFile) throws OSSException {
        // 创建 oss 对象
        OSSClient client = null;
        // 获取文件后缀
        String suffix = Objects.requireNonNull(multipartFile.getOriginalFilename()).substring(multipartFile.getOriginalFilename().lastIndexOf("."));

        // 拼接oss路劲 /hh-fms/2021/08/10/当前时间戳.后缀
        StringBuilder filePathSub = new StringBuilder();
        filePathSub.append(BUCKET_NAME);
        Calendar calendar = Calendar.getInstance();
        String filePath = filePathSub.append("/")
                .append(calendar.get(Calendar.YEAR)).append("/")
                .append(calendar.get(Calendar.MONTH) + 1).append("/")
                .append(calendar.get(Calendar.DAY_OF_MONTH)).append("/")
                .append(new Date().getTime()).append(suffix).toString();
        try (InputStream inputStream = multipartFile.getInputStream()) {
            // 存入oss
            client = new OSSClient(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
            ObjectMetadata objectMeta = new ObjectMetadata();
            objectMeta.setContentType(multipartFile.getContentType());
            objectMeta.setContentDisposition(multipartFile.getName());
            client.putObject(BUCKET_NAME, filePath, inputStream, objectMeta);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (client != null) {
                client.shutdown();
            }
        }
        UploadVideoDto uploadVideoDto = new UploadVideoDto();
        uploadVideoDto.setPath(BASE_URL+filePath);
        uploadVideoDto.setSize(multipartFile.getSize());
        //获取视频长度
        long duration = VideoUtil.getMp4Duration(uploadVideoDto.getPath());
        uploadVideoDto.setDuration(duration);
        return uploadVideoDto;
    }


    /**
     * @return java.lang.String
     * @author : GJY
     * @Description: // TODO
     * @date : 2021/8/11
     */
    public static String uploadFile(File file) throws OSSException {
        // 创建 oss 对象
        OSSClient client = null;

        // 获取文件后缀
        String suffix = file.getName().substring(file.getName().lastIndexOf("."));

        // 拼接oss路劲 /hh-fms/2021/08/10/当前时间戳.后缀
        StringBuilder filePathSub = new StringBuilder();
        filePathSub.append(BUCKET_NAME);
        Calendar calendar = Calendar.getInstance();
        String filePath = filePathSub.append("/")
                .append(calendar.get(Calendar.YEAR)).append("/")
                .append(calendar.get(Calendar.MONTH) + 1).append("/")
                .append(calendar.get(Calendar.DAY_OF_MONTH)).append("/")
                .append(UUID.randomUUID().toString().replaceAll("-", "")).append(suffix).toString();
        try (InputStream inputStream = new FileInputStream(file)) {
            // 存入oss
            client = new OSSClient(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
            ObjectMetadata objectMeta = new ObjectMetadata();
            client.putObject(BUCKET_NAME, filePath, inputStream, objectMeta);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (client != null) {
                client.shutdown();
            }
        }
        return BASE_URL + filePath;
    }
}
